package com.xiyuan.smartutils.client.http;

import com.xiyuan.smartutils.StrUtils;
import com.xiyuan.smartutils.Validates;
import com.xiyuan.smartutils.client.domain.ContentType;
import com.xiyuan.smartutils.client.domain.FileItem;
import com.xiyuan.smartutils.client.domain.FormData;

import java.io.File;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.util.Map;

/**
 * HTTPS 文件上传类
 *
 * @version v1.0.0 @author lgz 2017-9-21 新建与整理
 */
public class HttpUpload extends HttpClient {
    
    // 表单是否已经编码
    private boolean hasEncoded;
    
    private String encoding;
    private FormData form = new FormData();
    private String contentType;
    
    
    public HttpUpload(String url, ContentType enctype) {
        super(url, _POST_);
        this.encoding = _UTF_8_;
        this.form.setAutoEnctype(true);
        this.form.setEncoding(this.encoding);
        this.form.setEnctype(enctype);
    }
    
    public void setContentType(String contentType) {
        this.contentType = contentType;
    }
    
    public HttpUpload(String url) {
        this(url, null);
    }
    
    
    /**
     * 表单是否已经编码
     *
     * @return true|false
     */
    public boolean hasEncoded() {
        return hasEncoded;
    }
    
    /**
     * 表单是否已经编码; 针对 application/x-www-form-urlencoded 有效
     *
     * @param hasEncoded
     */
    public void setHasEncoded(boolean hasEncoded) {
        this.hasEncoded = hasEncoded;
    }
    
    public HttpUpload setEncoding(String encoding) {
        if (Validates.isNotBlank(encoding)) {
            this.encoding = StrUtils.trim(encoding);
        }
        
        this.form.setEncoding(encoding);
        return this;
    }
    
    /**
     * 自动表单类型,当有文件参数时 自动切换 multipart/form-data
     *
     * @param autoEncType 自动表单类型
     */
    public void setAutoEnctype(boolean autoEncType) {
        this.form.setAutoEnctype(autoEncType);
    }
    
    /***
     * 参数是否 已经 url 编码, 如果参数已经url编码则 构建 body 时则不会做url 编码。<br>
     * 只针对 application/x-www-form-urlencoded 有效
     * @param encoded true|false;
     */
    public void setEncoded(boolean encoded) {
        this.form.setEncoded(encoded);
    }
    
    
    public void addParam(String key, int value) {
        if (Validates.isBlank(key)) {
            return;
        }
        
        this.form.append(key, value);
    }
    
    public void addParam(String key, long value) {
        if (Validates.isBlank(key)) {
            return;
        }
        
        this.form.append(key, value);
    }
    
    public void addParam(String key, boolean value) {
        if (Validates.isBlank(key)) {
            return;
        }
        
        this.form.append(key, value);
    }
    
    public void addParam(String key, double value) {
        if (Validates.isBlank(key)) {
            return;
        }
        
        this.form.append(key, value);
    }
    
    public void addParam(String key, Number value) {
        if (Validates.isBlank(key)) {
            return;
        }
        
        this.form.append(key, value);
    }
    
    public void addParam(String key, String value) {
        if (Validates.isBlank(key)) {
            return;
        }
        
        this.form.append(key, value);
    }
    
    public void addAll(Map<String, String> paramMap) {
        this.form.appendAll(paramMap);
    }
    
    public void appendFiles(Map<String, FileItem> fileMap) {
        this.form.appendFiles(fileMap);
    }
    
    /**
     * 添加文件参数
     *
     * @param name     参数名
     * @param fileName 文件名
     * @param file     文件对象
     * @throws IllegalArgumentException throw IllegalArgumentException when name is empty or blank;
     */
    public void appendFile(String name, String fileName, File file) throws IllegalArgumentException {
        this.form.appendFile(name, fileName, file);
    }
    
    /**
     * 添加文件参数
     *
     * @param name 参数名
     * @param file 文件对象
     * @throws IllegalArgumentException throw IllegalArgumentException when name is empty or blank;
     */
    public void appendFile(String name, File file) throws IllegalArgumentException {
        this.form.appendFile(name, file == null ? "" : file.getName(), file);
    }
    
    /**
     * 添加文件参数
     *
     * @param name        参数名
     * @param fileName    文件名
     * @param mimeType    文件mimeType
     * @param fileContent 文件类型
     * @throws IllegalArgumentException throw IllegalArgumentException when name is empty or blank;
     */
    public void appendFile(String name, String fileName, byte[] fileContent, String mimeType) throws
                                                                                              IllegalArgumentException {
        this.form.appendFile(name, fileName, fileContent, mimeType);
    }
    
    protected boolean doPreRequestProperty() throws IOException {
        addRequestProperty(_CONTENT_TYPE_, contentType != null ? contentType : form.getContentType());
        addRequestProperty(_CONTENT_LENGTH_, form.getContentLength());
        setDoOutput(true);
        return true;
    }
    
    protected void doWriteContent(HttpURLConnection conn) throws IOException {
        this.form.setEncoded(hasEncoded);
        this.form.write(conn.getOutputStream());
    }
    
    public String getBodyAsString() {
        return form.createFormBody();
    }
}
